package net.esj.basic.service.impl;

import java.util.List;
import java.util.Locale;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.servlet.http.HttpSession;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validator;

import net.esj.basic.core.engine.support.MelonSupporter;
import net.esj.basic.core.engine.support.translator.TranslateException;
import net.esj.basic.core.engine.support.translator.Translator;
import net.esj.basic.core.engine.support.validator.exception.MelonValidateException;
import net.esj.basic.core.engine.support.validator.exception.ValidateMessage;
import net.esj.basic.core.view.filter.I18NFilter;
import net.esj.basic.core.view.support.vojo.TransObject;
import net.esj.basic.core.view.tools.ActionContext;
import net.esj.basic.exception.MelonRuntimeException;
import net.esj.basic.utils.ClassUtils;
import net.esj.basic.utils.Pagination;
import net.esj.basic.validate.defaults.DefaultJSR303Validator;

import org.apache.struts2.ServletActionContext;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceResolvable;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.i18n.LocaleContext;

public abstract class ServiceSupport implements LocaleContext,MessageSource{

	protected MessageSource messageSource;
	
	protected <T> Object autoTransVo(Object o,Class<T> targetClass){
		if(getTranslator()==null){
			throw new MelonRuntimeException("当前配置不支持自动类型转换!");
		}
		if(!ClassUtils.isInterfaceOf(targetClass, TransObject.class)){
			return o;
		}
		try{
			if(o instanceof Pagination){
				Pagination page = (Pagination) o;
				page.setQueryBuilder(null);
				if(targetClass !=page.getEntityClass()){
					List<T> list = (List<T>) getTranslator().translate(page.getRows(), targetClass);
					page.setRows(list);
				}
				return page;
			}else{
				Object reval = getTranslator().translate(o, targetClass);
				return reval;
			}
			
		}catch(TranslateException e){
			throw new MelonRuntimeException(e);
		}
	}
	
	protected Object autoTransPo(Object vo,Class<?> poClass){
		
		if(getTranslator()==null){
			throw new MelonRuntimeException("当前配置不支持自动类型转换!");
		}
		
		Object po;
		try {
			po = getTranslator().retrans(vo, poClass);
			return po;
		} catch (TranslateException e) {
			throw new MelonRuntimeException(e);
		}
	}
	
	public void validate(Object entity,Class<?>... clazz) throws MelonValidateException{
		
		if(getValidator()==null){
			throw new MelonRuntimeException("当前配置不支持自动类型效验!");
		}
		
		Set<ConstraintViolation<Object>> set = getValidator().validate(entity,clazz);
		HttpSession session = ActionContext.getSession();
		Locale locale = Locale.getDefault();
		if(session!=null){
			locale = (Locale) session.getAttribute(I18NFilter.STRUTS_I18N_KEY);
		}
		if(!set.isEmpty()){
			ValidateMessage vm = new ValidateMessage(set.size());
			for(ConstraintViolation<Object> tmp:set){
				vm.add(DefaultJSR303Validator.decipherValidateMessageInI18N(tmp, locale));
			}
			throw new MelonValidateException("效验不通过，请核查原因", vm);
		}
	}
	
	protected void packEsjValidateEx (ConstraintViolationException cvex) throws MelonValidateException{
		Set<ConstraintViolation<?>> set = cvex.getConstraintViolations();
		HttpSession session = ServletActionContext.getRequest().getSession();
		Locale locale = Locale.getDefault();
		if(session!=null){
			locale = (Locale) session.getAttribute(I18NFilter.STRUTS_I18N_KEY);
		}
		ValidateMessage vm = new ValidateMessage(set.size());
		for(ConstraintViolation<?> tmp:set){
			vm.add(DefaultJSR303Validator.decipherValidateMessageInI18N(tmp, locale));
		}
		throw new MelonValidateException("效验不通过，请核查原因", vm);
	}

	@Override
	public Locale getLocale() {
		HttpSession session = ServletActionContext.getRequest().getSession();
		if(session!=null){
			Locale locale = (Locale) session.getAttribute(I18NFilter.STRUTS_I18N_KEY);
			if(locale!=null){
				return locale;
			}
		}
		ActionContext ctx = ActionContext.getContext();
        if (ctx != null) {
            return ctx.getLocale();
        }
		return Locale.getDefault();
	}

	@Inject
	public void setMessageSource(MessageSource messageSource) {
		this.messageSource = messageSource;
	}

	@Override
	public String getMessage(MessageSourceResolvable resolvable, Locale locale)
			throws NoSuchMessageException {
		return messageSource.getMessage(resolvable, locale);
	}

	@Override
	public String getMessage(String code, Object[] args, Locale locale)
			throws NoSuchMessageException {
		return messageSource.getMessage(code, args, locale);
	}

	@Override
	public String getMessage(String code, Object[] args, String defaultMessage,
			Locale locale) {
		return messageSource.getMessage(code, args, defaultMessage, locale);
	}
	
	protected Translator getTranslator(){
		return MelonSupporter.getTranslator();
	}
	
	protected Validator getValidator(){
		return MelonSupporter.getValidator();
	}
	
}
